using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Windows.Forms;

namespace HslControls
{
	/// <summary>
	/// 曲线控件信息，可以用于显示一些实时的曲线信息，同时支持对曲线控件的一些简单的交互
	/// </summary>
	[Description("实时曲线控件，主要用来显示实时的曲线信息，不支持光标移动显示数据信息，支持简单的交互，显示隐藏曲线")]
	public class HslCurve : UserControl
	{
		private const int value_count_max = 4096;

		private float value_max_left = 100f;

		private float value_min_left = 0f;

		private float value_max_right = 100f;

		private float value_min_right = 0f;

		private int value_Segment = 5;

		private bool value_IsAbscissaStrech = false;

		private int value_StrechDataCountMax = 300;

		private bool value_IsRenderDashLine = true;

		private string textFormat = "HH:mm";

		private int value_IntervalAbscissaText = 100;

		private Random random = null;

		private string value_title = "";

		private int leftRight = 50;

		private int upDowm = 25;

		private Dictionary<string, HslCurveItem> data_list = null;

		private string[] data_text = null;

		private List<AuxiliaryLine> auxiliary_lines;

		private List<AuxiliaryLable> auxiliary_Labels;

		private List<HslMarkText> hslMarkTexts;

		private Font font_size9 = null;

		private Font font_size12 = null;

		private Brush brush_deep = null;

		private Pen pen_normal = null;

		private Pen pen_dash = null;

		private Color color_normal = Color.DeepPink;

		private Color color_deep = Color.DimGray;

		private Color color_dash = Color.Gray;

		private Color color_mark_font = Color.DodgerBlue;

		private Brush brush_mark_font = Brushes.DodgerBlue;

		private StringFormat format_left = null;

		private StringFormat format_right = null;

		private StringFormat format_center = null;

		private bool isRenderRightCoordinate = true;

		private int curveNameWidth = 100;

		private int pointsRadius = 0;

		/// <summary> 
		/// 必需的设计器变量。
		/// </summary>
		private IContainer components = null;

		/// <summary>
		/// 获取或设置控件的背景色
		/// </summary>
		[Browsable(true)]
		[Description("获取或设置控件的背景色")]
		[Category("HslControls")]
		[DefaultValue(typeof(Color), "Transparent")]
		[EditorBrowsable(EditorBrowsableState.Always)]
		public override Color BackColor
		{
			get
			{
				return base.BackColor;
			}
			set
			{
				base.BackColor = value;
			}
		}

		/// <summary>
		/// 获取或设置图形的纵坐标的最大值，该值必须大于最小值
		/// </summary>
		[Category("HslControls")]
		[Description("获取或设置图形的左纵坐标的最大值，该值必须大于最小值")]
		[Browsable(true)]
		[DefaultValue(100f)]
		public float ValueMaxLeft
		{
			get
			{
				return value_max_left;
			}
			set
			{
				value_max_left = value;
				Invalidate();
			}
		}

		/// <summary>
		/// 获取或设置图形的纵坐标的最小值，该值必须小于最大值
		/// </summary>
		[Category("HslControls")]
		[Description("获取或设置图形的左纵坐标的最小值，该值必须小于最大值")]
		[Browsable(true)]
		[DefaultValue(0f)]
		public float ValueMinLeft
		{
			get
			{
				return value_min_left;
			}
			set
			{
				value_min_left = value;
				Invalidate();
			}
		}

		/// <summary>
		/// 获取或设置图形的纵坐标的最大值，该值必须大于最小值
		/// </summary>
		[Category("HslControls")]
		[Description("获取或设置图形的右纵坐标的最大值，该值必须大于最小值")]
		[Browsable(true)]
		[DefaultValue(100f)]
		public float ValueMaxRight
		{
			get
			{
				return value_max_right;
			}
			set
			{
				value_max_right = value;
				Invalidate();
			}
		}

		/// <summary>
		/// 获取或设置图形的纵坐标的最小值，该值必须小于最大值
		/// </summary>
		[Category("HslControls")]
		[Description("获取或设置图形的右纵坐标的最小值，该值必须小于最大值")]
		[Browsable(true)]
		[DefaultValue(0f)]
		public float ValueMinRight
		{
			get
			{
				return value_min_right;
			}
			set
			{
				value_min_right = value;
				Invalidate();
			}
		}

		/// <summary>
		/// 获取或设置图形的纵轴分段数
		/// </summary>
		[Category("HslControls")]
		[Description("获取或设置图形的纵轴分段数")]
		[Browsable(true)]
		[DefaultValue(5)]
		public int ValueSegment
		{
			get
			{
				return value_Segment;
			}
			set
			{
				value_Segment = value;
				Invalidate();
			}
		}

		/// <summary>
		/// 获取或设置所有的数据是否强制在一个界面里显示
		/// </summary>
		[Category("HslControls")]
		[Description("获取或设置所有的数据是否强制在一个界面里显示")]
		[Browsable(true)]
		[DefaultValue(false)]
		public bool IsAbscissaStrech
		{
			get
			{
				return value_IsAbscissaStrech;
			}
			set
			{
				value_IsAbscissaStrech = value;
				Invalidate();
			}
		}

		/// <summary>
		/// 获取或设置拉伸模式下的最大数据量
		/// </summary>
		[Category("HslControls")]
		[Description("获取或设置拉伸模式下的最大数据量")]
		[Browsable(true)]
		[DefaultValue(300)]
		public int StrechDataCountMax
		{
			get
			{
				return value_StrechDataCountMax;
			}
			set
			{
				value_StrechDataCountMax = value;
				Invalidate();
			}
		}

		/// <summary>
		/// 获取或设置虚线是否进行显示
		/// </summary>
		[Category("HslControls")]
		[Description("获取或设置虚线是否进行显示")]
		[Browsable(true)]
		[DefaultValue(true)]
		public bool IsRenderDashLine
		{
			get
			{
				return value_IsRenderDashLine;
			}
			set
			{
				value_IsRenderDashLine = value;
				Invalidate();
			}
		}

		/// <summary>
		/// 获取或设置坐标轴及相关信息文本的颜色
		/// </summary>
		[Category("HslControls")]
		[Description("获取或设置坐标轴及相关信息文本的颜色")]
		[Browsable(true)]
		[DefaultValue(typeof(Color), "DimGray")]
		public Color ColorLinesAndText
		{
			get
			{
				return color_deep;
			}
			set
			{
				color_deep = value;
				InitializationColor();
				Invalidate();
			}
		}

		/// <summary>
		/// 获取或设置虚线的颜色
		/// </summary>
		[Category("HslControls")]
		[Description("获取或设置虚线的颜色")]
		[Browsable(true)]
		[DefaultValue(typeof(Color), "Gray")]
		public Color ColorDashLines
		{
			get
			{
				return color_dash;
			}
			set
			{
				color_dash = value;
				pen_dash?.Dispose();
				pen_dash = new Pen(color_dash);
				pen_dash.DashStyle = DashStyle.Custom;
				pen_dash.DashPattern = new float[2]
				{
					5f,
					5f
				};
				Invalidate();
			}
		}

		/// <summary>
		/// 获取或设置纵向虚线的分隔情况，单位为多少个数据
		/// </summary>
		[Category("HslControls")]
		[Description("获取或设置纵向虚线的分隔情况，单位为多少个数据")]
		[Browsable(true)]
		[DefaultValue(100)]
		public int IntervalAbscissaText
		{
			get
			{
				return value_IntervalAbscissaText;
			}
			set
			{
				value_IntervalAbscissaText = value;
				Invalidate();
			}
		}

		/// <summary>
		/// 获取或设置实时数据新增时文本相对应于时间的格式化字符串，默认HH:mm
		/// </summary>
		[Category("HslControls")]
		[Description("获取或设置实时数据新增时文本相对应于时间的格式化字符串，默认HH:mm")]
		[Browsable(true)]
		[DefaultValue("HH:mm")]
		public string TextAddFormat
		{
			get
			{
				return textFormat;
			}
			set
			{
				textFormat = value;
				Invalidate();
			}
		}

		/// <summary>
		/// 获取或设置图标的标题信息
		/// </summary>
		[Category("HslControls")]
		[Description("获取或设置图标的标题信息")]
		[Browsable(true)]
		[DefaultValue("")]
		public string Title
		{
			get
			{
				return value_title;
			}
			set
			{
				value_title = value;
				Invalidate();
			}
		}

		/// <summary>
		/// 获取或设置是否显示右侧的坐标系信息
		/// </summary>
		[Category("HslControls")]
		[Description("获取或设置是否显示右侧的坐标系信息")]
		[Browsable(true)]
		[DefaultValue(true)]
		public bool IsRenderRightCoordinate
		{
			get
			{
				return isRenderRightCoordinate;
			}
			set
			{
				isRenderRightCoordinate = value;
				Invalidate();
			}
		}

		/// <summary>
		/// 获取或设置曲线名称的布局宽度，默认为100
		/// </summary>
		[Browsable(true)]
		[Description("获取或设置曲线名称的布局宽度，默认为150")]
		[Category("HslControls")]
		[DefaultValue(100)]
		public int CurveNameWidth
		{
			get
			{
				return curveNameWidth;
			}
			set
			{
				if (value > 10)
				{
					curveNameWidth = value;
				}
			}
		}

		/// <summary>
		/// 获取或设置所有的数据点显示的半径大小，默认是0，不显示数据点
		/// </summary>
		[Browsable(true)]
		[Description("获取或设置所有的数据点显示的半径大小，默认是0，不显示数据点")]
		[Category("HslControls")]
		[DefaultValue(0)]
		public int PointsRadius
		{
			get
			{
				return pointsRadius;
			}
			set
			{
				pointsRadius = value;
				Invalidate();
			}
		}

		/// <summary>
		/// 实例化一个曲线显示的控件
		/// </summary>
		public HslCurve()
		{
			InitializeComponent();
			random = new Random();
			data_list = new Dictionary<string, HslCurveItem>();
			auxiliary_lines = new List<AuxiliaryLine>();
			hslMarkTexts = new List<HslMarkText>();
			auxiliary_Labels = new List<AuxiliaryLable>();
			format_left = new StringFormat
			{
				LineAlignment = StringAlignment.Center,
				Alignment = StringAlignment.Near
			};
			format_right = new StringFormat
			{
				LineAlignment = StringAlignment.Center,
				Alignment = StringAlignment.Far
			};
			format_center = new StringFormat
			{
				LineAlignment = StringAlignment.Center,
				Alignment = StringAlignment.Center
			};
			font_size9 = new Font("宋体", 9f);
			font_size12 = new Font("宋体", 12f);
			InitializationColor();
			pen_dash = new Pen(color_deep);
			pen_dash.DashStyle = DashStyle.Custom;
			pen_dash.DashPattern = new float[2]
			{
				5f,
				5f
			};
			SetStyle(ControlStyles.UserPaint | ControlStyles.SupportsTransparentBackColor, value: true);
			SetStyle(ControlStyles.ResizeRedraw, value: true);
			SetStyle(ControlStyles.OptimizedDoubleBuffer, value: true);
			SetStyle(ControlStyles.AllPaintingInWmPaint, value: true);
		}

		private void InitializationColor()
		{
			pen_normal?.Dispose();
			brush_deep?.Dispose();
			pen_normal = new Pen(color_deep);
			brush_deep = new SolidBrush(color_deep);
		}

		/// <summary>
		/// 设置曲线的横坐标文本，适用于显示一些固定的曲线信息
		/// </summary>
		/// <param name="descriptions">应该和曲线的点数一致</param>
		public void SetCurveText(string[] descriptions)
		{
			data_text = descriptions;
			Invalidate();
		}

		/// <summary>
		/// 新增或修改一条指定关键字的左参考系曲线数据，需要指定数据，颜色随机，没有数据上限，线条宽度为1
		/// </summary>
		/// <param name="key">曲线关键字</param>
		/// <param name="data">曲线的具体数据</param>
		public void SetLeftCurve(string key, float[] data)
		{
			SetLeftCurve(key, data, Color.FromArgb(random.Next(256), random.Next(256), random.Next(256)));
		}

		/// <summary>
		/// 新增或修改一条指定关键字的左参考系曲线数据，需要指定数据，颜色，没有数据上限，线条宽度为1
		/// </summary>
		/// <param name="key">曲线关键字</param>
		/// <param name="data">数据内容</param>
		/// <param name="lineColor">曲线颜色</param>
		public void SetLeftCurve(string key, float[] data, Color lineColor)
		{
			SetCurve(key, isLeft: true, data, lineColor, 1f, CurveStyle.LineSegment);
		}

		/// <summary>
		/// 新增或修改一条指定关键字的左参考系曲线数据，需要指定数据，颜色，没有数据上限，线条宽度为1
		/// </summary>
		/// <param name="key">曲线关键字</param>
		/// <param name="data">数据内容</param>
		/// <param name="lineColor">曲线颜色</param>
		/// <param name="style">曲线的样式</param>
		public void SetLeftCurve(string key, float[] data, Color lineColor, CurveStyle style)
		{
			SetCurve(key, isLeft: true, data, lineColor, 1f, style);
		}

		/// <summary>
		/// 新增或修改一条指定关键字的右参考系曲线数据，需要指定数据，颜色随机，没有数据上限，线条宽度为1
		/// </summary>
		/// <param name="key">曲线关键字</param>
		/// <param name="data">数据内容</param>
		public void SetRightCurve(string key, float[] data)
		{
			SetRightCurve(key, data, Color.FromArgb(random.Next(256), random.Next(256), random.Next(256)));
		}

		/// <summary>
		/// 新增或修改一条指定关键字的右参考系曲线数据，需要指定数据，颜色，没有数据上限，线条宽度为1
		/// </summary>
		/// <param name="key">曲线关键字</param>
		/// <param name="data">数据内容</param>
		/// <param name="lineColor">曲线颜色</param>
		public void SetRightCurve(string key, float[] data, Color lineColor)
		{
			SetCurve(key, isLeft: false, data, lineColor, 1f, CurveStyle.LineSegment);
		}

		/// <summary>
		/// 新增或修改一条指定关键字的右参考系曲线数据，需要指定数据，颜色，没有数据上限，线条宽度为1
		/// </summary>
		/// <param name="key">曲线关键字</param>
		/// <param name="data">数据内容</param>
		/// <param name="lineColor">曲线颜色</param>
		/// <param name="style">曲线的样式</param>
		public void SetRightCurve(string key, float[] data, Color lineColor, CurveStyle style)
		{
			SetCurve(key, isLeft: false, data, lineColor, 1f, style);
		}

		/// <summary>
		/// 新增或修改一条指定关键字的曲线数据，需要指定参考系及数据，颜色，线条宽度
		/// </summary>
		/// <param name="key">曲线关键字</param>
		/// <param name="isLeft">是否以左侧坐标轴为参照系</param>
		/// <param name="data">数据</param>
		/// <param name="lineColor">线条颜色</param>
		/// <param name="thickness">线条宽度</param>
		/// <param name="style">曲线的样式</param>
		public void SetCurve(string key, bool isLeft, float[] data, Color lineColor, float thickness, CurveStyle style)
		{
			if (data_list.ContainsKey(key))
			{
				if (data == null)
				{
					data = new float[0];
				}
				data_list[key].Data = data;
			}
			else
			{
				if (data == null)
				{
					data = new float[0];
				}
				data_list.Add(key, new HslCurveItem
				{
					Data = data,
					MarkText = new string[data.Length],
					LineThickness = thickness,
					LineColor = lineColor,
					IsLeftFrame = isLeft,
					Style = style
				});
				if (data_text == null)
				{
					data_text = new string[data.Length];
				}
			}
			Invalidate();
		}

		/// <summary>
		/// 移除指定关键字的曲线
		/// </summary>
		/// <param name="key">曲线关键字</param>
		public void RemoveCurve(string key)
		{
			if (data_list.ContainsKey(key))
			{
				data_list.Remove(key);
			}
			if (data_list.Count == 0)
			{
				data_text = new string[0];
			}
			Invalidate();
		}

		/// <summary>
		/// 移除所有的曲线
		/// </summary>
		public void RemoveAllCurve()
		{
			int count = data_list.Count;
			data_list.Clear();
			if (data_list.Count == 0)
			{
				data_text = new string[0];
			}
			if (count > 0)
			{
				Invalidate();
			}
		}

		/// <summary>
		/// 移除所有曲线的数据
		/// </summary>
		public void RemoveAllCurveData()
		{
			int count = data_list.Count;
			foreach (KeyValuePair<string, HslCurveItem> item in data_list)
			{
				item.Value.Data = new float[0];
				item.Value.MarkText = new string[0];
			}
			data_text = new string[0];
			if (count > 0)
			{
				Invalidate();
			}
		}

		/// <summary>
		/// 获取曲线图中已经存在的曲线对象，用于动态修改一些复杂的数据信息，如线宽，标记点，修改以前的数据内容等等
		/// </summary>
		/// <param name="key">关键字</param>
		/// <returns>曲线对象信息</returns>
		public HslCurveItem GetCurveItem(string key)
		{
			if (data_list.ContainsKey(key))
			{
				return data_list[key];
			}
			return null;
		}

		/// <summary>
		/// 将当前的图形曲线保存为图片内容，可用于存储本地的文件，或是打印到纸张，默认大小为控件的大小
		/// </summary>
		/// <returns>图片内容</returns>
		public Bitmap SaveToBitmap()
		{
			return SaveToBitmap(base.Width, base.Height);
		}

		/// <summary>
		/// 将当前的图形曲线保存为图片内容，可用于存储本地的文件，或是打印到纸张，使用指定的大小，显示的曲线可能和控件上的不一致
		/// </summary>
		/// <returns>图片内容</returns>
		public Bitmap SaveToBitmap(int width, int height)
		{
			Bitmap bitmap = new Bitmap(width, height);
			Graphics g = Graphics.FromImage(bitmap);
			OnPaint(new PaintEventArgs(g, new Rectangle(0, 0, width, height)));
			return bitmap;
		}

		/// <summary>
		/// 新增指定关键字曲线的一个数据，注意该关键字的曲线必须存在，否则无效
		/// </summary>
		/// <param name="key">新增曲线的关键字</param>
		/// <param name="values">数据值</param>
		/// <param name="markTexts">标记的文本信息</param>
		/// <param name="isUpdateUI">是否刷新界面</param>
		private void AddCurveData(string key, float[] values, string[] markTexts, bool isUpdateUI)
		{
			if ((values != null && values.Length < 1) || !data_list.ContainsKey(key))
			{
				return;
			}
			HslCurveItem curve = data_list[key];
			if (curve.Data != null)
			{
				if (value_IsAbscissaStrech)
				{
					HslHelper.AddArrayData(ref curve.Data, values, value_StrechDataCountMax);
					HslHelper.AddArrayData(ref curve.MarkText, markTexts, value_StrechDataCountMax);
				}
				else
				{
					HslHelper.AddArrayData(ref curve.Data, values, 4096);
					HslHelper.AddArrayData(ref curve.MarkText, markTexts, 4096);
				}
				if (isUpdateUI)
				{
					Invalidate();
				}
			}
		}

		private void AddCurveTime(int count)
		{
			AddCurveTime(count, DateTime.Now.ToString(textFormat));
		}

		private void AddCurveTime(int count, string text)
		{
			if (data_text != null)
			{
				string[] values = new string[count];
				for (int i = 0; i < values.Length; i++)
				{
					values[i] = text;
				}
				if (value_IsAbscissaStrech)
				{
					HslHelper.AddArrayData(ref data_text, values, value_StrechDataCountMax);
				}
				else
				{
					HslHelper.AddArrayData(ref data_text, values, 4096);
				}
			}
		}

		/// <summary>
		/// 新增指定关键字曲线的一个数据，注意该关键字的曲线必须存在，否则无效
		/// </summary>
		/// <param name="key">曲线的关键字</param>
		/// <param name="value">数据值</param>
		public void AddCurveData(string key, float value)
		{
			AddCurveData(key, new float[1]
			{
				value
			});
		}

		/// <summary>
		/// 新增指定关键字曲线的一个数据，注意该关键字的曲线必须存在，否则无效
		/// </summary>
		/// <param name="key">曲线的关键字</param>
		/// <param name="value">数据值</param>
		/// <param name="markText">标记的本文信息</param>
		public void AddCurveData(string key, float value, string markText)
		{
			AddCurveData(key, new float[1]
			{
				value
			}, new string[1]
			{
				markText
			});
		}

		/// <summary>
		/// 新增指定关键字曲线的一组数据，注意该关键字的曲线必须存在，否则无效
		/// </summary>
		/// <param name="key">曲线的关键字</param>
		/// <param name="values">数组值</param>
		public void AddCurveData(string key, float[] values)
		{
			AddCurveData(key, values, null);
		}

		/// <summary>
		/// 新增指定关键字曲线的一组数据，注意该关键字的曲线必须存在，否则无效
		/// </summary>
		/// <param name="key">曲线的关键字</param>
		/// <param name="values">数组值</param>
		/// <param name="markTexts">标记的本文信息</param>
		public void AddCurveData(string key, float[] values, string[] markTexts)
		{
			if (markTexts == null)
			{
				markTexts = new string[values.Length];
			}
			AddCurveData(key, values, markTexts, isUpdateUI: false);
			if (values != null && values.Length != 0)
			{
				AddCurveTime(values.Length);
			}
			Invalidate();
		}

		/// <summary>
		/// 新增指定关键字数组曲线的一组数据，注意该关键字的曲线必须存在，否则无效，一个数据对应一个数组
		/// </summary>
		/// <param name="keys">曲线的关键字数组</param>
		/// <param name="values">数组值</param>
		public void AddCurveData(string[] keys, float[] values)
		{
			AddCurveData(keys, values, null);
		}

		/// <summary>
		/// 新增指定关键字数组曲线的一组数据，注意该关键字的曲线必须存在，否则无效，一个数据对应一个数组
		/// </summary>
		/// <param name="axisText">自定义的横轴坐标数据</param>
		/// <param name="keys">曲线的关键字数组</param>
		/// <param name="values">数组值</param>
		public void AddCurveData(string axisText, string[] keys, float[] values)
		{
			AddCurveData(axisText, keys, values, null);
		}

		/// <summary>
		/// 新增指定关键字数组曲线的一组数据，注意该关键字的曲线必须存在，否则无效，一个数据对应一个数组
		/// </summary>
		/// <param name="keys">曲线的关键字数组</param>
		/// <param name="values">数组值</param>
		/// <param name="markTexts">标记的文本信息</param>
		public void AddCurveData(string[] keys, float[] values, string[] markTexts)
		{
			if (keys == null)
			{
				throw new ArgumentNullException("keys");
			}
			if (values == null)
			{
				throw new ArgumentNullException("values");
			}
			if (markTexts == null)
			{
				markTexts = new string[keys.Length];
			}
			if (keys.Length != values.Length)
			{
				throw new Exception("两个参数的数组长度不一致。");
			}
			if (keys.Length != markTexts.Length)
			{
				throw new Exception("两个参数的数组长度不一致。");
			}
			for (int i = 0; i < keys.Length; i++)
			{
				AddCurveData(keys[i], new float[1]
				{
					values[i]
				}, new string[1]
				{
					markTexts[i]
				}, isUpdateUI: false);
			}
			AddCurveTime(1);
			Invalidate();
		}

		/// <summary>
		/// 新增指定关键字数组曲线的一组数据，注意该关键字的曲线必须存在，否则无效，一个数据对应一个数组
		/// </summary>
		/// <param name="axisText">自定义的横轴坐标数据</param>
		/// <param name="keys">曲线的关键字数组</param>
		/// <param name="values">数组值</param>
		/// <param name="markTexts">标记的文本信息</param>
		public void AddCurveData(string axisText, string[] keys, float[] values, string[] markTexts)
		{
			if (keys == null)
			{
				throw new ArgumentNullException("keys");
			}
			if (values == null)
			{
				throw new ArgumentNullException("values");
			}
			if (markTexts == null)
			{
				markTexts = new string[keys.Length];
			}
			if (keys.Length != values.Length)
			{
				throw new Exception("两个参数的数组长度不一致。");
			}
			if (keys.Length != markTexts.Length)
			{
				throw new Exception("两个参数的数组长度不一致。");
			}
			for (int i = 0; i < keys.Length; i++)
			{
				AddCurveData(keys[i], new float[1]
				{
					values[i]
				}, new string[1]
				{
					markTexts[i]
				}, isUpdateUI: false);
			}
			AddCurveTime(1, axisText);
			Invalidate();
		}

		/// <summary>
		/// 设置一条曲线是否是可见的，如果该曲线不存在，则无效。
		/// </summary>
		/// <param name="key">关键字</param>
		/// <param name="visible">是否可见</param>
		public void SetCurveVisible(string key, bool visible)
		{
			if (data_list.ContainsKey(key))
			{
				HslCurveItem curve = data_list[key];
				curve.Visible = visible;
				Invalidate();
			}
		}

		/// <summary>
		/// 设置多条曲线是否是可见的，如果该曲线不存在，则无效。
		/// </summary>
		/// <param name="keys">关键字</param>
		/// <param name="visible">是否可见</param>
		public void SetCurveVisible(string[] keys, bool visible)
		{
			foreach (string key in keys)
			{
				if (data_list.ContainsKey(key))
				{
					HslCurveItem curve = data_list[key];
					curve.Visible = visible;
				}
			}
			Invalidate();
		}

		/// <summary>
		/// 新增一条左侧的辅助线，使用默认的文本颜色
		/// </summary>
		/// <param name="value">数据值</param>
		public void AddLeftAuxiliary(float value)
		{
			AddLeftAuxiliary(value, ColorLinesAndText);
		}

		/// <summary>
		/// 新增一条左侧的辅助线，使用指定的颜色
		/// </summary>
		/// <param name="value">数据值</param>
		/// <param name="lineColor">线条颜色</param>
		public void AddLeftAuxiliary(float value, Color lineColor)
		{
			AddLeftAuxiliary(value, lineColor, 1f, isDashLine: true);
		}

		/// <summary>
		/// 新增一条左侧的辅助线
		/// </summary>
		/// <param name="value">数据值</param>
		/// <param name="lineColor">线条颜色</param>
		/// <param name="lineThickness">线条宽度</param>
		/// <param name="isDashLine">是否是虚线</param>
		public void AddLeftAuxiliary(float value, Color lineColor, float lineThickness, bool isDashLine)
		{
			AddAuxiliary(value, lineColor, lineThickness, isDashLine, isLeft: true);
		}

		/// <summary>
		/// 新增一条右侧的辅助线，使用默认的文本颜色
		/// </summary>
		/// <param name="value">数据值</param>
		public void AddRightAuxiliary(float value)
		{
			AddRightAuxiliary(value, ColorLinesAndText);
		}

		/// <summary>
		/// 新增一条右侧的辅助线，使用指定的颜色
		/// </summary>
		/// <param name="value">数据值</param>
		/// <param name="lineColor">线条颜色</param>
		public void AddRightAuxiliary(float value, Color lineColor)
		{
			AddRightAuxiliary(value, lineColor, 1f, isDashLine: true);
		}

		/// <summary>
		/// 新增一条右侧的辅助线
		/// </summary>
		/// <param name="value">数据值</param>
		/// <param name="lineColor">线条颜色</param>
		/// <param name="lineThickness">线条宽度</param>
		/// <param name="isDashLine">是否是虚线的信息</param>
		public void AddRightAuxiliary(float value, Color lineColor, float lineThickness, bool isDashLine)
		{
			AddAuxiliary(value, lineColor, lineThickness, isDashLine, isLeft: false);
		}

		private void AddAuxiliary(float value, Color lineColor, float lineThickness, bool isDashLine, bool isLeft)
		{
			auxiliary_lines.Add(new AuxiliaryLine
			{
				Value = value,
				LineColor = lineColor,
				PenDash = new Pen(lineColor)
				{
					DashStyle = DashStyle.Custom,
					DashPattern = new float[2]
					{
						5f,
						5f
					}
				},
				PenSolid = new Pen(lineColor),
				IsDashStyle = isDashLine,
				IsLeftFrame = isLeft,
				LineThickness = lineThickness,
				LineTextBrush = new SolidBrush(lineColor)
			});
			Invalidate();
		}

		/// <summary>
		/// 移除所有的指定值的辅助曲线，包括左边的和右边的
		/// </summary>
		/// <param name="value"></param>
		public void RemoveAuxiliary(float value)
		{
			int removeCount = 0;
			for (int i = auxiliary_lines.Count - 1; i >= 0; i--)
			{
				if (auxiliary_lines[i].Value == value)
				{
					auxiliary_lines[i].Dispose();
					auxiliary_lines.RemoveAt(i);
					removeCount++;
				}
			}
			if (removeCount > 0)
			{
				Invalidate();
			}
		}

		/// <summary>
		/// 移除所有的辅助线
		/// </summary>
		public void RemoveAllAuxiliary()
		{
			int removeCount = auxiliary_lines.Count;
			auxiliary_lines.Clear();
			if (removeCount > 0)
			{
				Invalidate();
			}
		}

		/// <summary>
		/// 新增一条辅助标签
		/// </summary>
		/// <param name="auxiliaryLable">描述的标签值</param>
		public void AddAuxiliaryLabel(AuxiliaryLable auxiliaryLable)
		{
			auxiliary_Labels.Add(auxiliaryLable);
		}

		/// <summary>
		/// 移除指定的辅助标签
		/// </summary>
		/// <param name="auxiliaryLable">等待删除的对象</param>
		public void RemoveAuxiliaryLable(AuxiliaryLable auxiliaryLable)
		{
			if (auxiliary_Labels.Remove(auxiliaryLable))
			{
				Invalidate();
			}
		}

		/// <summary>
		/// 移除所有的辅助标签
		/// </summary>
		public void RemoveAllAuxiliaryLable()
		{
			int removeCount = auxiliary_Labels.Count;
			auxiliary_Labels.Clear();
			if (removeCount > 0)
			{
				Invalidate();
			}
		}

		/// <summary>
		/// 新增一个标记的文本信息
		/// </summary>
		/// <param name="markText">文本标记信息</param>
		public void AddMarkText(HslMarkText markText)
		{
			hslMarkTexts.Add(markText);
			if (data_list.Count > 0)
			{
				Invalidate();
			}
		}

		/// <summary>
		/// 移除一个标记的文本信息
		/// </summary>
		/// <param name="markText">文本标记信息</param>
		public void RemoveMarkText(HslMarkText markText)
		{
			hslMarkTexts.Remove(markText);
			if (data_list.Count > 0)
			{
				Invalidate();
			}
		}

		/// <summary>
		/// 移除所有的标记的文本信息
		/// </summary>
		public void RemoveAllMarkText()
		{
			hslMarkTexts.Clear();
			if (data_list.Count > 0)
			{
				Invalidate();
			}
		}

		/// <summary>
		/// 鼠标移动的信息
		/// </summary>
		/// <param name="e"></param>
		protected override void OnMouseMove(MouseEventArgs e)
		{
			base.OnMouseMove(e);
			bool result = false;
			foreach (KeyValuePair<string, HslCurveItem> item in data_list)
			{
				if (item.Value.TitleRegion.Contains(e.Location))
				{
					result = true;
					break;
				}
			}
			Cursor = (result ? Cursors.Hand : Cursors.Arrow);
		}

		/// <summary>
		/// 鼠标点击的信息
		/// </summary>
		/// <param name="e"></param>
		protected override void OnMouseDown(MouseEventArgs e)
		{
			base.OnMouseDown(e);
			foreach (KeyValuePair<string, HslCurveItem> item in data_list)
			{
				if (item.Value.TitleRegion.Contains(e.Location))
				{
					item.Value.LineRenderVisiable = !item.Value.LineRenderVisiable;
					Invalidate();
					break;
				}
			}
		}

		/// <summary>
		/// 重绘控件的基本外观
		/// </summary>
		/// <param name="e">重绘事件</param>
		protected override void OnPaint(PaintEventArgs e)
		{
			if (!Authorization.iashdiadasbdnajsdhjaf())
			{
				return;
			}
			Graphics g = e.Graphics;
			g.SmoothingMode = SmoothingMode.HighQuality;
			g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
			if (BackColor != Color.Transparent)
			{
				g.Clear(BackColor);
			}
			int width_totle = base.Width;
			int heigh_totle = base.Height;
			if (width_totle < 120 || heigh_totle < 60)
			{
				return;
			}
			Point[] pointsCoordinate = new Point[4]
			{
				new Point(leftRight - 1, upDowm - 8),
				new Point(leftRight - 1, heigh_totle - upDowm),
				new Point(width_totle - leftRight, heigh_totle - upDowm),
				new Point(width_totle - leftRight, upDowm - 8)
			};
			g.DrawLine(pen_normal, pointsCoordinate[0], pointsCoordinate[1]);
			g.DrawLine(pen_normal, pointsCoordinate[1], pointsCoordinate[2]);
			if (isRenderRightCoordinate)
			{
				g.DrawLine(pen_normal, pointsCoordinate[2], pointsCoordinate[3]);
			}
			if (!string.IsNullOrEmpty(value_title))
			{
				g.DrawString(value_title, font_size9, brush_deep, new Rectangle(0, 0, width_totle - 1, 20), format_center);
			}
			else if (data_list.Count > 0)
			{
				float x_start = leftRight + 10;
				foreach (KeyValuePair<string, HslCurveItem> item in data_list)
				{
					if (item.Value.Visible)
					{
						Pen pen = item.Value.LineRenderVisiable ? new Pen(item.Value.LineColor) : new Pen(Color.FromArgb(80, item.Value.LineColor));
						g.DrawLine(pen, x_start, 11f, x_start + 30f, 11f);
						g.DrawEllipse(pen, x_start + 8f, 4f, 14f, 14f);
						pen.Dispose();
						SolidBrush textBrush = item.Value.LineRenderVisiable ? new SolidBrush(item.Value.LineColor) : new SolidBrush(Color.FromArgb(80, item.Value.LineColor));
						g.DrawString(item.Key, Font, textBrush, new RectangleF(x_start + 35f, 2f, 120f, 18f), format_left);
						item.Value.TitleRegion = new RectangleF(x_start, 2f, 60f, 18f);
						textBrush.Dispose();
						x_start += (float)curveNameWidth;
					}
				}
			}
			for (int k = 0; k < auxiliary_Labels.Count; k++)
			{
				if (!string.IsNullOrEmpty(auxiliary_Labels[k].Text))
				{
					int start = (auxiliary_Labels[k].LocationX > 1f) ? ((int)auxiliary_Labels[k].LocationX) : ((int)(auxiliary_Labels[k].LocationX * (float)width_totle));
					int labelWidth = (int)g.MeasureString(auxiliary_Labels[k].Text, Font).Width + 3;
					Point[] labelBounds = new Point[6]
					{
						new Point(start, 11),
						new Point(start + 10, 20),
						new Point(start + labelWidth + 10, 20),
						new Point(start + labelWidth + 10, 0),
						new Point(start + 10, 0),
						new Point(start, 11)
					};
					g.FillPolygon(auxiliary_Labels[k].TextBack, labelBounds);
					g.DrawString(auxiliary_Labels[k].Text, Font, auxiliary_Labels[k].TextBrush, new Rectangle(start + 7, 0, labelWidth + 3, 20), format_center);
				}
			}
			HslHelper.PaintTriangle(g, brush_deep, new Point(leftRight - 1, upDowm - 8), 4, GraphDirection.Upward);
			if (isRenderRightCoordinate)
			{
				HslHelper.PaintTriangle(g, brush_deep, new Point(width_totle - leftRight, upDowm - 8), 4, GraphDirection.Upward);
			}
			for (int l = 0; l < auxiliary_lines.Count; l++)
			{
				if (auxiliary_lines[l].IsLeftFrame)
				{
					auxiliary_lines[l].PaintValue = HslHelper.ComputePaintLocationY(value_max_left, value_min_left, heigh_totle - upDowm - upDowm, auxiliary_lines[l].Value) + (float)upDowm;
				}
				else
				{
					auxiliary_lines[l].PaintValue = HslHelper.ComputePaintLocationY(value_max_right, value_min_right, heigh_totle - upDowm - upDowm, auxiliary_lines[l].Value) + (float)upDowm;
				}
			}
			for (int m = 0; m <= value_Segment; m++)
			{
				float valueTmpLeft = (float)((double)m * (double)(value_max_left - value_min_left) / (double)value_Segment + (double)value_min_left);
				float paintTmp = HslHelper.ComputePaintLocationY(value_max_left, value_min_left, heigh_totle - upDowm - upDowm, valueTmpLeft) + (float)upDowm;
				if (IsNeedPaintDash(paintTmp))
				{
					g.DrawLine(pen_normal, leftRight - 4, paintTmp, leftRight - 1, paintTmp);
					RectangleF rectTmp = new RectangleF(0f, paintTmp - 9f, leftRight - 4, 20f);
					g.DrawString(valueTmpLeft.ToString(), font_size9, brush_deep, rectTmp, format_right);
					if (isRenderRightCoordinate)
					{
						float valueTmpRight = (float)m * (value_max_right - value_min_right) / (float)value_Segment + value_min_right;
						g.DrawLine(pen_normal, width_totle - leftRight + 1, paintTmp, width_totle - leftRight + 4, paintTmp);
						rectTmp.Location = new PointF(width_totle - leftRight + 4, paintTmp - 9f);
						g.DrawString(valueTmpRight.ToString(), font_size9, brush_deep, rectTmp, format_left);
					}
					if (m > 0 && value_IsRenderDashLine)
					{
						g.DrawLine(pen_dash, leftRight, paintTmp, width_totle - leftRight, paintTmp);
					}
				}
			}
			if (value_IsRenderDashLine)
			{
				if (value_IsAbscissaStrech)
				{
					float offect = (float)(width_totle - leftRight * 2) * 1f / (float)(value_StrechDataCountMax - 1);
					int dataCount = CalculateDataCountByOffect(offect);
					for (int n = 0; n < value_StrechDataCountMax; n += dataCount)
					{
						if (n > 0 && n < value_StrechDataCountMax - 1)
						{
							g.DrawLine(pen_dash, (float)n * offect + (float)leftRight, upDowm, (float)n * offect + (float)leftRight, heigh_totle - upDowm - 1);
						}
						if (data_text != null && n < data_text.Length && (float)n * offect + (float)leftRight < (float)(data_text.Length - 1) * offect + (float)leftRight - 40f)
						{
							g.DrawString(layoutRectangle: new Rectangle((int)((float)n * offect), heigh_totle - upDowm + 1, leftRight * 2, upDowm), s: data_text[n], font: font_size9, brush: brush_deep, format: format_center);
						}
					}
					string[] array = data_text;
					if (array != null && array.Length > 1)
					{
						if (data_text.Length < value_StrechDataCountMax)
						{
							g.DrawLine(pen_dash, (float)(data_text.Length - 1) * offect + (float)leftRight, upDowm, (float)(data_text.Length - 1) * offect + (float)leftRight, heigh_totle - upDowm - 1);
						}
						g.DrawString(layoutRectangle: new Rectangle((int)((float)(data_text.Length - 1) * offect + (float)leftRight) - leftRight, heigh_totle - upDowm + 1, leftRight * 2, upDowm), s: data_text[data_text.Length - 1], font: font_size9, brush: brush_deep, format: format_center);
					}
				}
				else
				{
					int countTmp2 = width_totle - 2 * leftRight + 1;
					for (int i3 = leftRight; i3 < width_totle - leftRight; i3 += value_IntervalAbscissaText)
					{
						if (i3 != leftRight)
						{
							g.DrawLine(pen_dash, i3, upDowm, i3, heigh_totle - upDowm - 1);
						}
						if (data_text == null)
						{
							continue;
						}
						int right_limit = (countTmp2 > data_text.Length) ? data_text.Length : countTmp2;
						if (i3 - leftRight < data_text.Length && right_limit - (i3 - leftRight) > 40)
						{
							if (data_text.Length <= countTmp2)
							{
								g.DrawString(layoutRectangle: new Rectangle(i3 - leftRight, heigh_totle - upDowm + 1, leftRight * 2, upDowm), s: data_text[i3 - leftRight], font: font_size9, brush: brush_deep, format: format_center);
								continue;
							}
							g.DrawString(layoutRectangle: new Rectangle(i3 - leftRight, heigh_totle - upDowm + 1, leftRight * 2, upDowm), s: data_text[i3 - leftRight + data_text.Length - countTmp2], font: font_size9, brush: brush_deep, format: format_center);
						}
					}
					string[] array2 = data_text;
					if (array2 != null && array2.Length > 1)
					{
						if (data_text.Length >= countTmp2)
						{
							g.DrawString(layoutRectangle: new Rectangle(width_totle - leftRight - leftRight, heigh_totle - upDowm + 1, leftRight * 2, upDowm), s: data_text[data_text.Length - 1], font: font_size9, brush: brush_deep, format: format_center);
						}
						else
						{
							g.DrawLine(pen_dash, data_text.Length + leftRight - 1, upDowm, data_text.Length + leftRight - 1, heigh_totle - upDowm - 1);
							g.DrawString(layoutRectangle: new Rectangle(data_text.Length + leftRight - 1 - leftRight, heigh_totle - upDowm + 1, leftRight * 2, upDowm), s: data_text[data_text.Length - 1], font: font_size9, brush: brush_deep, format: format_center);
						}
					}
				}
			}
			for (int i4 = 0; i4 < auxiliary_lines.Count; i4++)
			{
				if (auxiliary_lines[i4].IsLeftFrame)
				{
					g.DrawLine(auxiliary_lines[i4].GetPen(), leftRight - 4, auxiliary_lines[i4].PaintValue, leftRight - 1, auxiliary_lines[i4].PaintValue);
					g.DrawString(layoutRectangle: new RectangleF(0f, auxiliary_lines[i4].PaintValue - 9f, leftRight - 4, 20f), s: auxiliary_lines[i4].Value.ToString(), font: font_size9, brush: auxiliary_lines[i4].LineTextBrush, format: format_right);
				}
				else
				{
					g.DrawLine(auxiliary_lines[i4].GetPen(), width_totle - leftRight + 1, auxiliary_lines[i4].PaintValue, width_totle - leftRight + 4, auxiliary_lines[i4].PaintValue);
					g.DrawString(layoutRectangle: new RectangleF(width_totle - leftRight + 4, auxiliary_lines[i4].PaintValue - 9f, leftRight - 4, 20f), s: auxiliary_lines[i4].Value.ToString(), font: font_size9, brush: auxiliary_lines[i4].LineTextBrush, format: format_left);
				}
				g.DrawLine(auxiliary_lines[i4].GetPen(), leftRight, auxiliary_lines[i4].PaintValue, width_totle - leftRight, auxiliary_lines[i4].PaintValue);
			}
			if (value_IsAbscissaStrech)
			{
				foreach (HslMarkText markText2 in hslMarkTexts)
				{
					foreach (KeyValuePair<string, HslCurveItem> line4 in data_list)
					{
						if (!line4.Value.Visible || !line4.Value.LineRenderVisiable || line4.Key != markText2.CurveKey)
						{
							continue;
						}
						float[] data = line4.Value.Data;
						if (data == null || data.Length <= 1)
						{
							continue;
						}
						float offect3 = (float)(width_totle - leftRight * 2) * 1f / (float)(value_StrechDataCountMax - 1);
						if (markText2.Index >= 0 && markText2.Index < line4.Value.Data.Length)
						{
							PointF center2 = new PointF((float)leftRight + (float)markText2.Index * offect3, HslHelper.ComputePaintLocationY(line4.Value.IsLeftFrame ? value_max_left : value_max_right, line4.Value.IsLeftFrame ? value_min_left : value_min_right, heigh_totle - upDowm - upDowm, line4.Value.Data[markText2.Index]) + (float)upDowm);
							g.FillEllipse(markText2.CircleBrush, new RectangleF(center2.X - 3f, center2.Y - 3f, 6f, 6f));
							switch ((markText2.PositionStyle == MarkTextPositionStyle.Auto) ? HslMarkText.CalculateDirectionFromDataIndex(line4.Value.Data, markText2.Index) : markText2.PositionStyle)
							{
							case MarkTextPositionStyle.Left:
								g.DrawString(markText2.MarkText, Font, markText2.TextBrush, new RectangleF(center2.X - 100f, center2.Y - (float)Font.Height, 100 - HslMarkText.MarkTextOffect, Font.Height * 2), format_right);
								break;
							case MarkTextPositionStyle.Up:
								g.DrawString(markText2.MarkText, Font, markText2.TextBrush, new RectangleF(center2.X - 100f, center2.Y - (float)Font.Height - (float)HslMarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
								break;
							case MarkTextPositionStyle.Right:
								g.DrawString(markText2.MarkText, Font, markText2.TextBrush, new RectangleF(center2.X + (float)HslMarkText.MarkTextOffect, center2.Y - (float)Font.Height, 100f, Font.Height * 2), format_left);
								break;
							case MarkTextPositionStyle.Down:
								g.DrawString(markText2.MarkText, Font, markText2.TextBrush, new RectangleF(center2.X - 100f, center2.Y + (float)HslMarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
								break;
							}
						}
					}
				}
				foreach (HslCurveItem line3 in data_list.Values)
				{
					if (!line3.Visible || !line3.LineRenderVisiable)
					{
						continue;
					}
					float[] data2 = line3.Data;
					if (data2 == null || data2.Length <= 1)
					{
						continue;
					}
					float offect2 = (float)(width_totle - leftRight * 2) * 1f / (float)(value_StrechDataCountMax - 1);
					List<PointF> listPoints2 = new List<PointF>(line3.Data.Length);
					for (int i2 = 0; i2 < line3.Data.Length; i2++)
					{
						if (!float.IsNaN(line3.Data[i2]))
						{
							PointF point3 = default(PointF);
							point3.X = (float)leftRight + (float)i2 * offect2;
							point3.Y = HslHelper.ComputePaintLocationY(line3.IsLeftFrame ? value_max_left : value_max_right, line3.IsLeftFrame ? value_min_left : value_min_right, heigh_totle - upDowm - upDowm, line3.Data[i2]) + (float)upDowm;
							listPoints2.Add(point3);
							if (string.IsNullOrEmpty(line3.MarkText[i2]))
							{
								continue;
							}
							using Brush circleBrush = new SolidBrush(line3.LineColor);
							g.FillEllipse(circleBrush, new RectangleF(point3.X - 3f, point3.Y - 3f, 6f, 6f));
							switch (HslMarkText.CalculateDirectionFromDataIndex(line3.Data, i2))
							{
							case MarkTextPositionStyle.Left:
								g.DrawString(line3.MarkText[i2], Font, circleBrush, new RectangleF(point3.X - 100f, point3.Y - (float)Font.Height, 100 - HslMarkText.MarkTextOffect, Font.Height * 2), format_right);
								break;
							case MarkTextPositionStyle.Up:
								g.DrawString(line3.MarkText[i2], Font, circleBrush, new RectangleF(point3.X - 100f, point3.Y - (float)Font.Height - (float)HslMarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
								break;
							case MarkTextPositionStyle.Right:
								g.DrawString(line3.MarkText[i2], Font, circleBrush, new RectangleF(point3.X + (float)HslMarkText.MarkTextOffect, point3.Y - (float)Font.Height, 100f, Font.Height * 2), format_left);
								break;
							case MarkTextPositionStyle.Down:
								g.DrawString(line3.MarkText[i2], Font, circleBrush, new RectangleF(point3.X - 100f, point3.Y + (float)HslMarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
								break;
							}
						}
						else
						{
							DrawLineCore(g, line3, listPoints2, pointsRadius);
							listPoints2.Clear();
						}
					}
					DrawLineCore(g, line3, listPoints2, pointsRadius);
				}
			}
			else
			{
				foreach (HslMarkText markText in hslMarkTexts)
				{
					foreach (KeyValuePair<string, HslCurveItem> line2 in data_list)
					{
						if (!line2.Value.Visible || !line2.Value.LineRenderVisiable || line2.Key != markText.CurveKey)
						{
							continue;
						}
						float[] data3 = line2.Value.Data;
						if (data3 != null && data3.Length > 1 && markText.Index >= 0 && markText.Index < line2.Value.Data.Length)
						{
							PointF center = new PointF(leftRight + markText.Index, HslHelper.ComputePaintLocationY(line2.Value.IsLeftFrame ? value_max_left : value_max_right, line2.Value.IsLeftFrame ? value_min_left : value_min_right, heigh_totle - upDowm - upDowm, line2.Value.Data[markText.Index]) + (float)upDowm);
							g.FillEllipse(markText.CircleBrush, new RectangleF(center.X - 3f, center.Y - 3f, 6f, 6f));
							switch ((markText.PositionStyle == MarkTextPositionStyle.Auto) ? HslMarkText.CalculateDirectionFromDataIndex(line2.Value.Data, markText.Index) : markText.PositionStyle)
							{
							case MarkTextPositionStyle.Left:
								g.DrawString(markText.MarkText, Font, markText.TextBrush, new RectangleF(center.X - 100f, center.Y - (float)Font.Height, 100 - HslMarkText.MarkTextOffect, Font.Height * 2), format_right);
								break;
							case MarkTextPositionStyle.Up:
								g.DrawString(markText.MarkText, Font, markText.TextBrush, new RectangleF(center.X - 100f, center.Y - (float)Font.Height - (float)HslMarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
								break;
							case MarkTextPositionStyle.Right:
								g.DrawString(markText.MarkText, Font, markText.TextBrush, new RectangleF(center.X + (float)HslMarkText.MarkTextOffect, center.Y - (float)Font.Height, 100f, Font.Height * 2), format_left);
								break;
							case MarkTextPositionStyle.Down:
								g.DrawString(markText.MarkText, Font, markText.TextBrush, new RectangleF(center.X - 100f, center.Y + (float)HslMarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
								break;
							}
						}
					}
				}
				foreach (HslCurveItem line in data_list.Values)
				{
					if (!line.Visible || !line.LineRenderVisiable)
					{
						continue;
					}
					float[] data4 = line.Data;
					if (data4 == null || data4.Length <= 1)
					{
						continue;
					}
					int countTmp = width_totle - 2 * leftRight + 1;
					List<PointF> listPoints = new List<PointF>(line.Data.Length);
					if (line.Data.Length <= countTmp)
					{
						for (int j = 0; j < line.Data.Length; j++)
						{
							if (!float.IsNaN(line.Data[j]))
							{
								PointF point2 = default(PointF);
								point2.X = leftRight + j;
								point2.Y = HslHelper.ComputePaintLocationY(line.IsLeftFrame ? value_max_left : value_max_right, line.IsLeftFrame ? value_min_left : value_min_right, heigh_totle - upDowm - upDowm, line.Data[j]) + (float)upDowm;
								listPoints.Add(point2);
								DrawMarkPoint(g, line.MarkText[j], point2, line.LineColor, HslMarkText.CalculateDirectionFromDataIndex(line.Data, j));
							}
							else
							{
								DrawLineCore(g, line, listPoints, pointsRadius);
								listPoints.Clear();
							}
						}
					}
					else
					{
						for (int i = 0; i < countTmp; i++)
						{
							int index = i + line.Data.Length - countTmp;
							if (!float.IsNaN(line.Data[index]))
							{
								PointF point = default(PointF);
								point.X = leftRight + i;
								point.Y = HslHelper.ComputePaintLocationY(line.IsLeftFrame ? value_max_left : value_max_right, line.IsLeftFrame ? value_min_left : value_min_right, heigh_totle - upDowm - upDowm, line.Data[index]) + (float)upDowm;
								listPoints.Add(point);
								DrawMarkPoint(g, line.MarkText[index], point, line.LineColor, HslMarkText.CalculateDirectionFromDataIndex(line.Data, index));
							}
							else
							{
								DrawLineCore(g, line, listPoints, pointsRadius);
								listPoints.Clear();
							}
						}
					}
					DrawLineCore(g, line, listPoints, pointsRadius);
				}
			}
			base.OnPaint(e);
		}

		public static void DrawLineCore(Graphics g, HslCurveItem line, List<PointF> listPoints, int pointsRadius)
		{
			if (listPoints.Count <= 1)
			{
				return;
			}
			using (Pen penTmp = new Pen(line.LineColor, line.LineThickness))
			{
				if (line.Style == CurveStyle.LineSegment)
				{
					g.DrawCurve(penTmp, listPoints.ToArray());
				}
				else if (line.Style == CurveStyle.Curve)
				{
					g.DrawLines(penTmp, listPoints.ToArray());
				}
				else
				{
					for (int j = 0; j < listPoints.Count - 1; j++)
					{
						PointF center = new PointF(listPoints[j + 1].X, listPoints[j].Y);
						g.DrawLine(penTmp, listPoints[j], center);
						if (line.Style == CurveStyle.StepLine)
						{
							g.DrawLine(penTmp, center, listPoints[j + 1]);
						}
					}
				}
			}
			if (pointsRadius <= 0)
			{
				return;
			}
			using Brush pointBrush = new SolidBrush(line.LineColor);
			for (int i = 0; i < listPoints.Count; i++)
			{
				g.FillEllipse(pointBrush, listPoints[i].X - (float)pointsRadius, listPoints[i].Y - (float)pointsRadius, pointsRadius * 2, pointsRadius * 2);
			}
		}

		private void DrawMarkPoint(Graphics g, string markText, PointF center, Color color, MarkTextPositionStyle markTextPosition)
		{
			if (!string.IsNullOrEmpty(markText))
			{
				using Brush brush = new SolidBrush(color);
				DrawMarkPoint(g, markText, center, brush, markTextPosition);
			}
		}

		private void DrawMarkPoint(Graphics g, string markText, PointF center, Brush brush, MarkTextPositionStyle markTextPosition)
		{
			if (!string.IsNullOrEmpty(markText))
			{
				g.FillEllipse(brush, new RectangleF(center.X - 3f, center.Y - 3f, 6f, 6f));
				switch (markTextPosition)
				{
				case MarkTextPositionStyle.Left:
					g.DrawString(markText, Font, brush, new RectangleF(center.X - 100f, center.Y - (float)Font.Height, 100 - HslMarkText.MarkTextOffect, Font.Height * 2), format_right);
					break;
				case MarkTextPositionStyle.Up:
					g.DrawString(markText, Font, brush, new RectangleF(center.X - 100f, center.Y - (float)Font.Height - (float)HslMarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
					break;
				case MarkTextPositionStyle.Right:
					g.DrawString(markText, Font, brush, new RectangleF(center.X + (float)HslMarkText.MarkTextOffect, center.Y - (float)Font.Height, 100f, Font.Height * 2), format_left);
					break;
				case MarkTextPositionStyle.Down:
					g.DrawString(markText, Font, brush, new RectangleF(center.X - 100f, center.Y + (float)HslMarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
					break;
				}
			}
		}

		private bool IsNeedPaintDash(float paintValue)
		{
			for (int i = 0; i < auxiliary_lines.Count; i++)
			{
				if (Math.Abs(auxiliary_lines[i].PaintValue - paintValue) < (float)font_size9.Height)
				{
					return false;
				}
			}
			return true;
		}

		private int CalculateDataCountByOffect(float offect)
		{
			if (value_IntervalAbscissaText > 0)
			{
				return value_IntervalAbscissaText;
			}
			if (offect > 40f)
			{
				return 1;
			}
			offect = 40f / offect;
			return (int)Math.Ceiling(offect);
		}

		/// <summary> 
		/// 清理所有正在使用的资源。
		/// </summary>
		/// <param name="disposing">如果应释放托管资源，为 true；否则为 false。</param>
		protected override void Dispose(bool disposing)
		{
			if (disposing && components != null)
			{
				components.Dispose();
			}
			base.Dispose(disposing);
		}

		/// <summary> 
		/// 设计器支持所需的方法 - 不要修改
		/// 使用代码编辑器修改此方法的内容。
		/// </summary>
		private void InitializeComponent()
		{
			SuspendLayout();
			base.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
			BackColor = System.Drawing.Color.Transparent;
			base.Name = "HslCurve";
			base.Size = new System.Drawing.Size(417, 205);
			ResumeLayout(false);
		}
	}
}
